import EventDefines from "../Constants/EventDefines";
import G from "../Utilities/Global";
import ClickItem from "./ClickItem";
import Constants from "../Constants/Constants";
import Stack from "../Lib/Stack";
import MapAssetStruct from "../Structs/MapAssetStruct";
import MapData from "../Map/MapData";
import C from "../Configs/Config";

/**
 * 编辑界面
 * created by Five on 2018-11-5 18:32:02
 * TODO 考虑用命令模式,实现编辑时的undo redo 功能
 */
const { ccclass, property } = cc._decorator;

@ccclass
export default class EditLayer extends cc.Component {

    @property(cc.Node)
    nameEdit: cc.Node = null;
    @property(cc.Node)
    timeEdit: cc.Node = null;
    @property(cc.Node)
    ItemView: cc.Node = null;
    @property(cc.Node)
    detailNode: cc.Node = null;
    @property(cc.Node)
    scrollContent: cc.Node = null;
    // 地图信息(默认的)
    public MapData: MapData = null;
    // 选择的墙体
    public SelectedAsset: MapAssetStruct = null;
    // 防止移动的玩意儿
    private _isTouched: boolean = false;
    // 有效点击区域
    private _validAreaY: number = 575;
    // 编辑步骤记录，用于还原
    private _stepRecord: Stack<any> = null;
    // 一次连续编辑
    private _oneStep: Array<any> = null;

    constructor() {
        super();
        this._stepRecord = new Stack<any>();
        this._oneStep = new Array<any>();
    }

    // 传入已经编辑过的地图信息,直接显示出来
    public SetMapData(data: MapData) {
        this.MapData = data;
        if (this.MapData == null) {
            this.MapData = new MapData();
            this.MapData.MapID = 1;
        }
        this.nameEdit.getComponent(cc.EditBox).string = this.MapData.MapName;
        this.timeEdit.getComponent(cc.EditBox).string = this.MapData.TimeLimit + "";
    }

    private _lastTouchPos: cc.Vec2;
    start() {
        if (this.MapData == null)
            return;
        this.node.on(cc.Node.EventType.TOUCH_START, (event: cc.Event.EventTouch) => {
            if (this._isTouched)
                return;
            this.makeWay(event.touch.getLocation())
            this._isTouched = true;
            this._lastTouchPos = event.touch.getLocation();
        }, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, () => {
            this._isTouched = false;
            if (this._oneStep.length > 0) {
                this._stepRecord.push(this._oneStep);
                delete this._oneStep;
                this._oneStep = new Array<any>();
            }
        }, this);
        this.node.on(cc.Node.EventType.TOUCH_END, () => {
            this._isTouched = false;
            if (this._oneStep.length > 0) {
                this._stepRecord.push(this._oneStep);
                delete this._oneStep;
                this._oneStep = new Array<any>();
            }
        }, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, (event: cc.Event.EventTouch) => {
            if (!this._isTouched) return;
            let touch = event.touch.getLocation();
            let dis = G().Calc.Distance(touch, this._lastTouchPos);
            if (dis > Constants.ENTITY_EDGE / 2) {
                this.makeWay(event.touch.getLocation())
                this._lastTouchPos = touch;
            }
        }, this);
        this.node.on(EventDefines.ENTITY_CLICKED, (event: cc.Event) => {
            this.imageEntity(event.target);
        }, this);
        this.node.on(EventDefines.ENTITY_CLEAR, () => {
            this.clearEntity();
        }, this);
        this.drawRectangle();
        this.detailNode.active = false;
    }

    /**辅助观看的格子 */
    private drawRectangle() {
        let ctx = this.addComponent(cc.Graphics);
        ctx.clear();
        ctx.lineWidth = 2;
        ctx.strokeColor = cc.Color.CYAN;
        let winSize = this.MapData.Size;
        // 所有的坐标都是以中心为原点的,然而点击是以左下角为原点,棒棒哒
        // 横
        let edge = Constants.ENTITY_EDGE;
        for (let i = 0; i < this.MapData.Size.height / edge; i++) {
            let lineH = i * edge - winSize.height / 2;
            let pos = new cc.Vec2(0 - winSize.width / 2, lineH);
            ctx.moveTo(pos.x, pos.y);
            ctx.lineTo(winSize.width, lineH);
            ctx.stroke();
        }
        // 竖
        for (let i = 0; i < this.MapData.Size.width / edge; i++) {
            let pos = new cc.Vec2(i * edge - winSize.width / 2, 0 - winSize.height / 2);
            ctx.moveTo(pos.x, pos.y);
            ctx.lineTo(i * edge - winSize.width / 2, winSize.height);
            ctx.stroke();
        }
    }

    private imageEntity(target: cc.Node) {
        this.SelectedAsset = target.getComponent(ClickItem).DataStruct;
    }

    private clearEntity() {
        this.SelectedAsset = null;
    }

    /**
     * 铺路工人
     * @param touchPoint 要铺设的位置
     */
    private async makeWay(touchPoint: cc.Vec2) {
        // cc.log('touchPoint = ' + touchPoint);
        // let newPos = touchPoint.add(cc.v2(32, 32));
        cc.log('touchPoint = ' + touchPoint);
        let loc = G().Calc.PositionToLocation(touchPoint);
        cc.log('touchPoint = ' + touchPoint + " loc = " + loc);
        // 只可以撤销当次编辑的内容
        if (G().CurScene.AddTile(loc, this.SelectedAsset))
            this._oneStep.push(loc);
    }

    public SaveEdit(event) {
        let name = this.nameEdit.getComponent(cc.EditBox).string;
        let time = this.timeEdit.getComponent(cc.EditBox).string;
        this.MapData.MapName = name;
        this.MapData.TimeLimit = +time;

        cc.log(JSON.stringify(this.MapData));
        cc.log(this.MapData);
    }

    openDetail() {
        this.detailNode.active = !this.detailNode.active;
        this.openMap();
    }

    openMap() {
        this.scrollContent.removeAllChildren();
        C().Map.Maps.forEach((_, k) => {
            this.add2Content(k, (t: cc.Event.EventTouch) => {
                let mName = t.target.getComponent(cc.Label).string;
                G().CurScene.JumpTo(mName);
                t.stopPropagation();
            });
        })
        let size = this.scrollContent.getContentSize();
        this.scrollContent.setContentSize(size.width, C().Map.Maps.size * 40);
    }

    openBg() {
        this.scrollContent.removeAllChildren();
        C().Background.Assets.forEach((asset => {
            this.add2Content(asset.name, (t: cc.Event.EventTouch) => {
                G().CurScene.SetBackground(t.target.getComponent(cc.Label).string);
                t.stopPropagation();
            });
        }))
        let size = this.scrollContent.getContentSize();
        this.scrollContent.setContentSize(size.width, C().Background.Assets.length * 40);
    }

    add2Content(name: string, callback: Function) {
        let node = new cc.Node();
        let label = node.addComponent(cc.Label);
        label.string = name;
        label.fontSize = 24;
        node.color = cc.Color.BLACK;
        node.on(cc.Node.EventType.TOUCH_START, callback);
        this.scrollContent.addChild(node);
    }

    public Undo() {
        if (this._stepRecord.empty())
            return;
        let arr = this._stepRecord.pop();
        G().CurScene.RemoveTiles(arr);
    }
}